package com.huage.courseplatform.framework.core.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huage.courseplatform.framework.config.RedisConfiguration;
import com.huage.courseplatform.framework.utils.ReflectUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import javax.annotation.Resource;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.huage.courseplatform.framework.constant.ConfigConstants.SERVICE_CACHE_HOUR_TIME;


/**
 * xxh 抽取通用实现类三级缓存管理
 * @param <M> mapper
 * @param <T> entity
 */
@Slf4j
public class BaseServiceImpl<M extends BaseMapper<T>,T> extends ServiceImpl<M,T>{

    @Resource
    RedisTemplate redisTemplate;

    private Object cacheName;


    public BaseServiceImpl(){
        String classNameAndPassage = this.getClass().getName();
        this.cacheName  = classNameAndPassage.substring(classNameAndPassage.lastIndexOf(".")+1,classNameAndPassage.lastIndexOf("I"));
        log.info("开启Redis-service缓存: cacheName:"+cacheName+",缓存时间为:"+SERVICE_CACHE_HOUR_TIME+"小时");
    }

    public Class<T> getEntityClass() {
        ParameterizedType parameterizedType = (ParameterizedType)this.getClass().getGenericSuperclass();
        Type entityType = parameterizedType.getActualTypeArguments()[1];
        return (Class)entityType;
    }



    @Override
    public T getById(Serializable id) {
        String key = "Service:" + cacheName+":"+"id::"+id;
        //缓存不为空，返回缓存
        T jsonObj = (T) redisTemplate.opsForValue().get(key);
         if(ObjectUtils.isNotEmpty(jsonObj)){
             return jsonObj;
         }
        //缓存为空，返回数据加载缓存
        T entity = super.getById(id);
        if(ObjectUtils.isNotEmpty(entity)){
            redisTemplate.opsForValue().set(key,entity,SERVICE_CACHE_HOUR_TIME, TimeUnit.HOURS);
        }

        return entity;
    }

    @Override
    public <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper) {
        String key = "Service:" + cacheName+":"+"page::"+page.getPages()+"-"+page.getSize()+"qw:"+queryWrapper.getExpression();
        //缓存不为空，返回缓存
        E jsonObjList = (E) redisTemplate.opsForValue().get(key);
        if(ObjectUtils.isNotEmpty(jsonObjList)){
            return jsonObjList;
        }
        //缓存为空，返回数据加载缓存
        page = super.page(page,queryWrapper);
        if(ObjectUtils.isNotEmpty(page)){
            redisTemplate.opsForValue().set(key,page,SERVICE_CACHE_HOUR_TIME, TimeUnit.HOURS);
        }
        return page;
    }


    @Override
    public boolean saveOrUpdate(T entity) {
        String id = ReflectUtils.getFieldValue(entity,"id");
        String pageKey = "Service:" + cacheName+":"+"page::*";
        String key = "Service:" + cacheName+":"+"id::"+id;
        //清空对应ID缓存
        if(redisTemplate.hasKey(key)){
            redisTemplate.delete(key);
        }
        //清空分页缓存
        Set<String> pageKeys = redisTemplate.keys(pageKey);
        redisTemplate.delete(pageKeys);

        return super.saveOrUpdate(entity);

    }

    @Override
    public boolean save(T entity) {
        //清空分页缓存
        String pageKey = "Service:" + cacheName+":"+"page::*";
        Set<String> pageKeys = redisTemplate.keys(pageKey);
        redisTemplate.delete(pageKeys);
        return super.save(entity);
    }

    @Override
    public boolean removeById(Serializable id) {
        String pageKey = "Service:" + cacheName+":"+"page::*";
        String key = "Service:" + cacheName+":"+"id::"+id;
        //清空对应ID缓存
        if(redisTemplate.hasKey(key)){
            redisTemplate.delete(key);
        }
        //清空分页缓存
        Set<String> pageKeys = redisTemplate.keys(pageKey);
        redisTemplate.delete(pageKeys);

        return super.removeById(id);
    }

    @Override
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        String pageKey = "Service:" + cacheName+"::"+"page:*";
        String key = "Service:" + cacheName+":"+"id::";
        //清空id集合缓存
        Set<String> idsKeys = new HashSet<>();
        idList.forEach(id->{
            String idKey = key+id;
            idsKeys.add(idKey);

        });
        redisTemplate.delete(idsKeys);
        //清空分页缓存
        Set<String> pageKeys = redisTemplate.keys(pageKey);
        redisTemplate.delete(pageKeys);
        return super.removeByIds(idList);
    }


}
